package com.ly.common.models.common;


import com.ly.common.constant.MessageConstant;
import com.ly.common.exception.ParamsVaildErrException;
import com.ly.common.utils.MapUtil;
import com.ly.common.utils.StringUtil;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 公共请求类(根据实际情况使用)
 * @Auther: lzw
 * @Date: 2018/6/4
 */
public class RequestMessage<T> implements Serializable {
    private String source;
    private String data;
    private String token;
    private String version;
    private DataMap<String, Object> dataMap;


    /**
     * 获取bean
     * @param objClass
     * @return
     */
    public T getBean(Class objClass){
        return (T) MapUtil.convertMap(objClass, dataMap);
    }

    /**
     * 校验bean
     * @param objClass  实体类
     */
    public void vaildBean(Class objClass) {
        Map<String, String> errorMap = vaildBeanErr(objClass,null);
        if (errorMap != null && errorMap.size() > 0) {
            throw new ParamsVaildErrException(MessageConstant.ERR_PARAMETER.getCode(), MessageConstant.ERR_PARAMETER.getDesc(), errorMap);
        }else if(errorMap==null){
            throw new ParamsVaildErrException(MessageConstant.FAILURE.getCode(), MessageConstant.FAILURE.getDesc());
        }
    }

    /**
     * 校验bean
     */
    public static void vaildBeanStatic(Object obj) {
        Map<String, String> errorMap = vaildBeanErrStatic(obj, null);
        if (errorMap != null && errorMap.size() > 0) {
            throw new ParamsVaildErrException(MessageConstant.ERR_PARAMETER.getCode(), MessageConstant.ERR_PARAMETER.getDesc(), errorMap);
        }else if(errorMap==null){
            throw new ParamsVaildErrException(MessageConstant.FAILURE.getCode(), MessageConstant.FAILURE.getDesc());
        }
    }

    /**
     * 校验bean
     * @param objClass  实体类
     * @param vaildType 分组
     */
    public void vaildBean(Class objClass, Class vaildType) {
        Map<String, String> errorMap = vaildBeanErr(objClass, vaildType);
            if (errorMap != null && errorMap.size() > 0) {
                throw new ParamsVaildErrException(MessageConstant.ERR_PARAMETER.getCode(), MessageConstant.ERR_PARAMETER.getDesc(), errorMap);
            }else if(errorMap==null){
                throw new ParamsVaildErrException(MessageConstant.FAILURE.getCode(), MessageConstant.FAILURE.getDesc());
            }
    }
    /**
     * 校验bean
     * @param vaildType 分组
     */
    public static void vaildBeanStatic(Object obj,Class vaildType) {
        Map<String, String> errorMap = vaildBeanErrStatic(obj, vaildType);
        if (errorMap != null && errorMap.size() > 0) {
            throw new ParamsVaildErrException(MessageConstant.ERR_PARAMETER.getCode(), MessageConstant.ERR_PARAMETER.getDesc(), errorMap);
        }else if(errorMap==null){
            throw new ParamsVaildErrException(MessageConstant.FAILURE.getCode(), MessageConstant.FAILURE.getDesc());
        }
    }


    /**
     * 校验bean
     *
     * @param objClass
     * @param vaildType
     * @return
     */
    private Map<String, String> vaildBeanErr(Class objClass, Class vaildType){
        Map<String, String> errorMap = new HashMap<String, String>();
        try {
            T passportlends = (T) MapUtil.convertMap(objClass, dataMap);
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            Validator validator = factory.getValidator();
            Set<ConstraintViolation<T>> constraintViolations=null;
            if(vaildType==null){
                constraintViolations = validator
                        .validate(passportlends);
            }else{
                constraintViolations = validator
                        .validate(passportlends, vaildType);
            }
            for (ConstraintViolation<T> constraintViolation : constraintViolations) {
                errorMap.put(constraintViolation.getPropertyPath().toString(), constraintViolation.getMessage());
            }
        } catch (Exception e) {
            errorMap = null;
        }
        return errorMap;
    }

    /**
     * 校验bean
     *
     * @param vaildType
     * @return
     */
    private static Map<String, String> vaildBeanErrStatic(Object passportlends, Class vaildType){
        Map<String, String> errorMap = new HashMap<String, String>();
        try {
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            Validator validator = factory.getValidator();
            Set<ConstraintViolation<Object>> constraintViolations=null;
            if(vaildType==null){
                constraintViolations = validator
                        .validate(passportlends);
            }else{
                constraintViolations = validator
                        .validate(passportlends, vaildType);
            }
            for (ConstraintViolation constraintViolation : constraintViolations) {
                errorMap.put(constraintViolation.getPropertyPath().toString(), constraintViolation.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
            errorMap = null;
        }
        return errorMap;
    }


    public String getData() {
        return data;
    }

    public void setData(String data){
        this.data = data;
       ObjectMapper objMapper = new ObjectMapper();
        dataMap = StringUtil.jsonStrToMap(data);
        if (dataMap == null) {
            throw new ParamsVaildErrException(MessageConstant.ERR_PARAMETER.getCode(), MessageConstant.ERR_PARAMETER.getDesc());
        }
    }

    public DataMap<String, Object> getDataMap() {
        return dataMap;
    }

    public void setDataMap(DataMap<String, Object> dataMap) {
        this.dataMap = dataMap;
    }

    public String getSource() {
        return source;
    }

    public void setSource(String source) {
        this.source = source;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }


    @Override
    public String toString() {
        return "RequestMessage{" +
                "source='" + source + '\'' +
                ", data='" + data + '\'' +
                ", token='" + token + '\'' +
                ", version='" + version + '\'' +
                ", dataMap=" + dataMap +
                '}';
    }


}
